package nccloud.api.baseapp.impl.oa;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

import com.sm.misc.BASE64Encoder;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.bs.framework.common.InvocationInfoProxy;
import nc.bs.framework.common.NCLocator;
import nc.bs.framework.server.ISecurityTokenCallback;
import nc.itf.uap.busibean.ISysInitQry;
import nc.jdbc.framework.processor.BeanListProcessor;
import nc.jdbc.framework.processor.ColumnProcessor;
import nc.jdbc.framework.processor.MapListProcessor;
import nc.vo.bc.pub.util.SysParaInitQuery;
import nc.vo.oa.msg.IMessageIntegrateOAService;
import nc.vo.pub.BusinessException;
import nc.vo.pubapp.pattern.exception.ExceptionUtils;
import nc.vo.sm.UserVO;
import ncc.bs.utils.GetParamConfigUtil;
import ncc.bs.utils.GloableConfigParam;
import ncc.bs.utils.InputLogger;
import nccloud.message.vo.NCCApproveMessageVO;
import nccloud.message.vo.NCCTodoMessageVO;
import nccloud.putitf.riart.billtype.IBillRelatedAppService;
import nccloud.security.impl.SignatureTookKit;

/**
 * 
 * @ClassName: MessageIntegrateOAImpl
 * @Description: 单点登录及消息集成后台实现服务类
 * 
 */
@SuppressWarnings("unchecked")
public class MessageIntegrateOAImpl implements IMessageIntegrateOAService {
	private static final String LoggName = "oalog";

	private static BaseDAO baseDAO;

	private static BaseDAO getBaseDAO() {
		if (baseDAO == null) {
			baseDAO = new BaseDAO();
		}
		return baseDAO;
	}

	/**
	 * 获取消息代办URL
	 * 
	 * @param usercode   用户编码
	 * @param pk_message 消息主键
	 * @return
	 */
	@Override
	public String getOpenMsgUrl(String usercode, String pk_message, String type) {
		InputLogger.info(LoggName,"--------OA获取单点登录及消息待办URL，【处理类：nccloud.api.hrpub.impl.oa.MessageIntegrateOAImpl 方法：getOpenMsgUrl()】。");
		InvocationInfoProxy.getInstance().setUserDataSource("bip");//设置数据源
		String nccaddr =  GetParamConfigUtil.queryGroupSysParam("NCCIP");
		// 获取token
		String token = getNCCToken(usercode, nccaddr);
		String url ;
		if("".equals(pk_message) || pk_message==null) {
			InputLogger.info("oalog","--------第三方当前的操作为单点登录，操作用户为：【"+usercode+"】,消息主键为：【"+pk_message+"】，操作类型为：【"+type+"】");
			 url = nccaddr+ "/nccloud/resources/uap/rbac/thirdpartylogin/main/index.html?accesstoken=" + token + "&redirect_uri="
					+ nccaddr + "/nccloud/resources/workbench/public/common/main/index.html";
			InputLogger.info("oalog", "单点登录地址URL:【"+url+"】................");
		}else {
			InputLogger.info("oalog","开始进行组装重定向URL................");
			// 组装重定向URL
			String redirectUrl = getRedirectURL(usercode, pk_message, type);
			if("".equals(redirectUrl)) {
				return null;
			}
			 url = nccaddr + "/nccloud/resources/uap/rbac/thirdpartylogin/main/index.html?accesstoken=" + token
					+ "&redirect_uri=" + nccaddr + "/nccloud/resources/workbench/public/common/main/index.html#/ifr?ifr="
					+ redirectUrl;
			InputLogger.info("oalog","单点到审批界面的URL地址为【"+url+"】................");
		}
		
		return url;
	}


	@Override
	public String getOpenSingleLoginleUrl(String usercode, String pk_message, String type, String loginType) {
		InputLogger.info(LoggName,"--------OA获取单点登录及消息待办URL，【处理类：nccloud.api.hrpub.impl.oa.MessageIntegrateOAImpl 方法：getOpenMsgUrl()】。");
		InvocationInfoProxy.getInstance().setUserDataSource("bip");//设置数据源
		String nccaddr =  GetParamConfigUtil.queryGroupSysParam("NCCIP");
		// 获取token
		String token = getNCCToken(usercode, nccaddr);
		String url  = "" ;
		if("".equals(pk_message) || pk_message==null) {
			url = nccaddr+ "/nccloud/resources/uap/rbac/thirdpartylogin/main/index.html?accesstoken=" + token + "&redirect_uri=" ;
			InputLogger.info("oalog","--------第三方当前的操作为单点登录，操作用户为：【"+usercode+"】,消息主键为：【"+pk_message+"】，操作类型为：【"+type+"】");
			if("YFK".equals(loginType)){
				url = GetParamConfigUtil.queryGroupSysParam("YFKIP");
            }else if("HT".equals(loginType)){
				url +=  GetParamConfigUtil.queryGroupSysParam("HTIP");
            }else{//默认单点登录
				url += (  nccaddr +"/nccloud/resources/workbench/public/common/main/index.html");
			}
			InputLogger.info("oalog", "单点登录地址URL:【"+url+"】................");
		}else {
			InputLogger.info("oalog","开始进行组装重定向URL................");
			// 组装重定向URL
			String redirectUrl = getRedirectURL(usercode, pk_message, type);
			if("".equals(redirectUrl)) {
				return null;
			}
			url = nccaddr + "/nccloud/resources/uap/rbac/thirdpartylogin/main/index.html?accesstoken=" + token
					+ "&redirect_uri=" + nccaddr + "/nccloud/resources/workbench/public/common/main/index.html#/ifr?ifr="
					+ redirectUrl;
			InputLogger.info("oalog","单点到审批界面的URL地址为【"+url+"】................");
		}

		return url;
	}

	private String getSysInitString(String name) {
		return SysParaInitQuery.getParaString("GLOBLE00000000000000", name);
	}

	/**
	 * 获取全部代办
	 * 
	 * @return
	 */
	public String getAllTreatedSql() {
		String sql = "SELECT s.name                as orgname," + "       a.subject," + "       a.content,"
				+ "       a.billno," + "       bd_psndoc_send.code   as sendcode,"
				+ "       bd_psndoc_inuser.code as inusercode," + "       a.sendtime," + "       a.pk_message"
				+ "  from sm_msg_approve a" + "  left join sm_msg_user" + "    on a.pk_message = sm_msg_user.pk_message"
				+ "  left join sm_user c" + "    on a.sender = c.cuserid" + "  left join sm_user d"
				+ "    on sm_msg_user.pk_user = d.cuserid"
				+ "  left join (select * from pub_wf_instance where workflow_type in (2, 4)) i"
				+ "    on i.billid = a.billid" + "  left join org_orgs s" + "    on s.pk_org = a.pk_org"
				+ "  left join bd_psndoc bd_psndoc_send" + "    on c.pk_psndoc = bd_psndoc_send.pk_psndoc"
				+ "  join bd_psndoc bd_psndoc_inuser" + "    on d.pk_psndoc = bd_psndoc_inuser.pk_psndoc"
				+ " where sm_msg_user.isdelete = 'N'" + "   and sm_msg_user.destination = 'inbox'"
				+ "   and a.msgtype = 'nc' and a.billtype != '6302'";

		return sql;
	}

	/**
	 * 获取未处理代办SQL
	 * 
	 * @return
	 */
	public String getUnTreatedSql() {
		String sql = "SELECT s.name                as orgname," + "       a.subject," + "       a.content,"
				+ "       a.billno," + "       bd_psndoc_send.code   as sendcode,"
				+ "       bd_psndoc_inuser.code as inusercode," + "       a.sendtime," + "       a.pk_message"
				+ "  from sm_msg_approve a" + "  left join sm_msg_user" + "    on a.pk_message = sm_msg_user.pk_message"
				+ "  left join sm_user c" + "    on a.sender = c.cuserid" + "  left join sm_user d"
				+ "    on sm_msg_user.pk_user = d.cuserid"
				+ "  left join (select * from pub_wf_instance where workflow_type in (2, 4)) i"
				+ "    on i.billid = a.billid" + "  left join org_orgs s" + "    on s.pk_org = a.pk_org"
				+ "  left join bd_psndoc bd_psndoc_send" + "    on c.pk_psndoc = bd_psndoc_send.pk_psndoc"
				+ "  join bd_psndoc bd_psndoc_inuser" + "    on d.pk_psndoc = bd_psndoc_inuser.pk_psndoc"
				+ " where sm_msg_user.isdelete = 'N'" + "   and sm_msg_user.destination = 'inbox'"
				+ "   and a.msgtype = 'nc' and a.billtype != '6302'" + "   and sm_msg_user.isread = 'N'";

		return sql;
	}

	/**
	 * 获取已处理代办SQL
	 * 
	 * @return
	 */
	public String getTreatedSql() {
		String sql = "SELECT s.name                as orgname," + "       a.subject," + "       a.content,"
				+ "       a.billno," + "       bd_psndoc_send.code   as sendcode,"
				+ "       bd_psndoc_inuser.code as inusercode," + "       a.sendtime," + "       a.pk_message"
				+ "  from sm_msg_approve a" + "  left join sm_msg_user" + "    on a.pk_message = sm_msg_user.pk_message"
				+ "  left join sm_user c" + "    on a.sender = c.cuserid" + "  left join sm_user d"
				+ "    on sm_msg_user.pk_user = d.cuserid"
				+ "  left join (select * from pub_wf_instance where workflow_type in (2, 4)) i"
				+ "    on i.billid = a.billid" + "  left join org_orgs s" + "    on s.pk_org = a.pk_org"
				+ "  left join bd_psndoc bd_psndoc_send" + "    on c.pk_psndoc = bd_psndoc_send.pk_psndoc"
				+ "  join bd_psndoc bd_psndoc_inuser" + "    on d.pk_psndoc = bd_psndoc_inuser.pk_psndoc"
				+ " where sm_msg_user.isdelete = 'N'" + "   and sm_msg_user.destination = 'inbox'"
				+ "   and a.msgtype = 'nc' and a.billtype != '6302'" + "   and sm_msg_user.isread = 'Y'";

		return sql;
	}

	/**
	 * 获取未处理代办SQL
	 * 
	 * @return
	 */
	public String getAllUnTreatedSql() {
		String sql = "SELECT s.name as orgname, " + "       a.subject, " + "       a.content, " + "       a.billno, "
				+ "       c.user_code as sendcode, " + "       d.user_code as inusercode, " + "       a.sendtime, "
				+ "       a.pk_message " + "  from sm_msg_approve a " + "  left join sm_msg_user "
				+ "    on a.pk_message = sm_msg_user.pk_message " + "  left join sm_user c "
				+ "    on a.sender = c.cuserid " + "  left join sm_user d " + "    on sm_msg_user.pk_user = d.cuserid "
				+ "  left join (select * from pub_wf_instance where workflow_type in (2, 4)) i "
				+ "    on i.billid = a.billid " + "  left join org_orgs s " + "    on s.pk_org = a.pk_org "
				+ " where sm_msg_user.isdelete = 'N' " + "   and sm_msg_user.destination = 'inbox' "
				+ "   and a.msgtype = 'nc' " + "   and sm_msg_user.isread = 'N' ";
		return sql;
	}

	public String getUserPk(String code) throws BusinessException {
		String pk = null;
		try {
			String sql = "select cuserid from sm_user t where t.user_code = '" + code + "' and t.dr = 0";
			pk = (String) getBaseDAO().executeQuery(sql, new ColumnProcessor());

		} catch (Exception e) {
			InputLogger.error(LoggName,"根据usercode查询用户失败,失败信息:" + e.getMessage());
			throw new BusinessException("根据usercode查询用户失败,失败信息:" + e.getMessage());
		}
		return pk;
	}

	private static String requestURL(String url) throws Exception {
		String result = "";
		// 创建post方法的实例
		HttpPost postMethod = new HttpPost(url);
		// 设置中文编码
		StringEntity entityParams = new StringEntity("", "UTF-8");
		// 设置内容编码类型
		entityParams.setContentType("application/json");
		// 设置请求参数
		postMethod.setEntity(entityParams);
		// 执行postMethod，获取内容
		HttpResponse response = new DefaultHttpClient().execute(postMethod);
		// 根据状态码，判断是否成功
		if (response.getStatusLine().getStatusCode() != 200)
			// 处理异常
			ExceptionUtils.wrappBusinessException("方法失败:" + response.getStatusLine());
		// 得到结果集
		result = EntityUtils.toString(response.getEntity(), "utf-8");
		// 判断是否出现异常
		if (result.toLowerCase().contains("exception")) {
			InputLogger.error(LoggName,"根据usercode查询用户失败,失败信息:" +result);
			ExceptionUtils.wrappBusinessException(result);
		}
		return result.replaceAll("\\\\", "");
	}

	/**
	 * 获取NCCToken
	 * 
	 * @param usercode 用户编码
	 * @param addr     NCC地址
	 * @return
	 */
	private static String getNCCToken(String usercode, String addr) {
		InputLogger.info("oalog","开始准备获取当前请求的token，方法为【getNCCToken】.............");
		/**
		 * 需要配置： 1.NCC地址 2.数据源名称，sysConfig启动查看 3.账套编码
		 */
		String token = "";
		// 数据源名称
		String dsname = InvocationInfoProxy.getInstance().getUserDataSource();
		try {
			ISysInitQry sysinit = NCLocator.getInstance().lookup(ISysInitQry.class);
			// 数据库中sm_oauth_security注册的内容
//			String client_id = GetParamConfigUtil.queryGroupSysParam(GloableConfigParam.NCC_CLIENT_ID);
			String client_id = "oaauth";
			if(StringUtils.isBlank(client_id)) {
				ExceptionUtils.wrappBusinessException("获取第三方id失败，请到业务参数-全局维护 参数代码为 CLIENT_ID ");
			}
//			String client_security = GetParamConfigUtil.queryGroupSysParam( GloableConfigParam.NCC_CLIENT_SECRET);
			String client_security = "24a9ab02d297124237a8f89c1611135f";
			String ts = (System.currentTimeMillis() + "").substring(0, 6);
			String security = new BASE64Encoder().encode(
					SignatureTookKit.digestSign(usercode.getBytes(), (usercode + client_security + ts).getBytes()));
//			String busicentercode = GetParamConfigUtil.queryGroupSysParam( GloableConfigParam.NCC_ACCOUTCODE);// 若存在多个账套，加上该参数指定一个账套，若不指定则遍历所有账套中是否包含usercode
			String busicentercode = "001";// 若存在多个账套，加上该参数指定一个账套，若不指定则遍历所有账套中是否包含usercode
			String encode = URLEncoder.encode(security, StandardCharsets.UTF_8);
			String url = addr + "/service/genThirdPartyAccessToken?type=type_security&dsname=" + dsname + "&usercode="
					+ usercode + "&client_id=" + client_id + "&security=" + encode
					+ "&ts=" + ts + "&busicentercode=" + busicentercode; //  "&busicentercode=" + busicentercode;
			token = requestURL(url);
		} catch (Exception e) {
			InputLogger.error(LoggName,"获取NCC Token失败,失败信息:" + e.getMessage());
			ExceptionUtils.wrappBusinessException(e.getMessage());
		}
		InputLogger.info("oalog","token获取成功.........");
		return token;
	}

	/**
	 * 获取消息代办打开URL
	 * 
	 * @param usercode   用户编码
	 * @param pk_message 消息主键
	 * @param type
	 * @return
	 */
	@Override
	public String getRedirectURL(String usercode, String pk_message, String type) {
		InputLogger.info("oalog","获取重定向地址操作，【方法名为：getRedirectURL】................");
		String url = "";
		try {
			// 模拟登陆
			NCLocator.getInstance().lookup(ISecurityTokenCallback.class).token("NCSystem".getBytes(),"pfxx".getBytes());
//			String dataSource = MsgSyncUtils.queryGroupSysParam("BD900");
			InvocationInfoProxy.getInstance().setUserDataSource("");
			String userSql = "select cuserid, pk_group from sm_user where user_code = '" + usercode + "' and dr = 0 ";
			List<Map<String, String>> uList = (List<Map<String, String>>) getBaseDAO().executeQuery(userSql,
					new MapListProcessor());
			if (uList.isEmpty()) {
				return url;
			}
			// 当前servlet的单点登录后没有设置到用户信息,该参数必须设置
			InvocationInfoProxy.getInstance().setUserId(uList.get(0).get("cuserid"));
			InvocationInfoProxy.getInstance().setGroupId(uList.get(0).get("pk_group"));
			String addr = "";
			String tablename = "";
			if ("worklist".equals(type)) {
				tablename = "sm_msg_approve";
				//获取跳转的地址
				NCCApproveMessageVO approveVO = (NCCApproveMessageVO) getBaseDAO().retrieveByPK(NCCApproveMessageVO.class, pk_message) ;
			} else if ("todo".equals(type)) {
				tablename = "sm_msg_todo";
				NCCTodoMessageVO todoVO = (NCCTodoMessageVO) getBaseDAO().retrieveByPK(NCCTodoMessageVO.class, pk_message) ;
				//获取业务消息跳转的地址
				addr = todoVO.getParams().split("PCURL=")[1];
//				updateMessageStatus(pk_message); //业务消息放入代办
//				return url;
			} else {
//				tablename = "sm_msg_notice";
				updateMessageStatus(pk_message);
				return url;
			}
			String sql = "select billtype,billid,pk_message from " + tablename + " where pk_detail = '" + pk_message + "' ";

			List<Map<String, String>> slist = (List<Map<String, String>>) getBaseDAO().executeQuery(sql,
					new MapListProcessor());
			if (slist.isEmpty()) {
				return url;
			}
			String billtype = slist.get(0).get("billtype");
			String billid = slist.get(0).get("billid");
			pk_message = slist.get(0).get("pk_message");
			
			
			// 根据单据类型查询对应的appcode等信息
			Map<String, String> map = NCLocator.getInstance().lookup(IBillRelatedAppService.class).getTargetURL(null,
					null, billtype);
			if (map == null) {
				return url;
			}
			// 记录url地址
			StringBuilder sb = new StringBuilder();
			// 业务消息跳转到业务中心
			if(("todo").equals(type)) {
//				sb.append(addr); // 消息中心-业务中心
//				sb.append("&status=browse&scene=todo"); 
//				sb.append("/nccloud/resources/pu/pu/poorder/main/index.html#/transfer20?appcode=400400400&pagecode=400400400_20to21&id=1001ZZ1000000001K9JI&status=browse&scene=todo&c=400400400&p=400400400_20to21&c=400400400&p=400400400_20to21&ar=0001Z810000000039R8O&n=请购单维护&b1=供应链&b2=采购管理&b3=请购单"); 
				
				
				sb.append("/nccloud/resources/uap/msgcenter/message/main/index.html#/?msgType=todo&appcode=10160502&c=10160502&p=10160502TODO"
						+"&ar=" + billid// 业务单据pk 前端辅助查询
						+ "&n=业务中心"); // &b1=动态建模平台&b2=流程管理&b3=审批管理
			}else if (("worklist").equals(type)) {
				sb.append("/nccloud/resources/uap/msgcenter/message/approveDetail/index.html#/"); // 应用注册-审批中心-待办详情固定地址
				sb.append("?pk_message="); // 消息pk
				sb.append(pk_message);
				sb.append("&pageMsgType=approve&appcode=10160501&pagecode=10160501APPROVE"); // 审批中心固定参数
				sb.append("&c="); // 上级页面编码
				sb.append(map.get("appcode"));
				sb.append("&p="); // 单据页面编码
				sb.append(map.get("pagecode"));
				sb.append("&n=审批中心&p=10160501APPROVE&n=审批中心"); // 显示层级(非固定值,可自定义)
//				sb.append("&checknote=&n=审批中心&n=审批中心&b1=动态建模平台&b2=流程管理&b3=审批管理"); // 显示层级(非固定值,可自定义)
				sb.append("&ar=" + billid); // 业务单据pk 前端辅助查询
			} else {
				// 通知消息("notice").equals(type)
				// 更新状态为已读

//				sb.append("/nccloud/resources/uap/msgcenter/message/main/index.html#/"); 
//				sb.append("?pk_message="); // 消息pk
//				sb.append(pk_message);
//				sb.append("&curPageType=notice&appcode=10160504&pagecode=10160504NOTICE"); // 
//				sb.append("&c=10160504"); // 上级页面编码
//				sb.append("&p=10160504NOTICE"); // 单据页面编码
//			    sb.append("&n=通知中心&b1=动态建模平台&b2=流程管理&b3=审批管理"); //显示层级(非固定值,可自定义)
//				sb.append("&ar=" + billid); // 业务单据pk 前端辅助查询

			}
//			sb.append("&needRefresh=true"); // 控制是否刷新
			url = sb.toString();
			url = URLEncoder.encode(URLEncoder.encode(url)); // 二次加密,前端固定二次解码

			// &b1=动态建模平台&b2=流程管理&b3=审批管理
			url = url+"&b2%25E6%25B5%2581%25E7%25A8%258B%25E7%25AE%25A1%25E7%2590%2586&b3=%25E5%25AE%25A1%25E6%2589%25B9%25E7%25AE%25A1%25E7%2590%2586&c=10160501&ar=0001Z0100000000042SD";
		} catch (BusinessException e) {
			InputLogger.error(LoggName,"获取消息待办重定向地址失败,失败信息:" + e.getMessage());
			ExceptionUtils.wrappBusinessException(e.getMessage());
		}
		return url;
	}

	public static UserVO getUserVO(String shortname) throws BusinessException {
		UserVO uservo = null;
		String sql = "select * from sm_user t where t.dr = 0 and t.enablestate = 2 and   user_code   = '" + shortname
				+ "'";
		List<UserVO> data = (List<UserVO>) getBaseDAO().executeQuery(sql,
				new BeanListProcessor(UserVO.class));
		if (data != null && data.size() != 0) {
			if (data.size() == 1) {
				uservo = data.get(0);
			} else if (data.size() > 1) {
				InputLogger.error(LoggName,"根据" + shortname + ",找到多条用户,请检查数据！！！");
				throw new BusinessException("根据" + shortname + ",找到多条用户,请检查数据！！！");
			}
		} else {
			InputLogger.error(LoggName,"根据" + shortname + ",无法找到对应有效的用户信息请检查！！！");
			throw new BusinessException("根据" + shortname + ",无法找到对应有效的用户信息请检查！！！");
		}
		return uservo;

	}

	/**
	 * 根据消息主键更新消息为已读
	 * 
	 * @author chenwb
	 * @date 2022年3月10日下午2:05:20
	 */
	private void updateMessageStatus(String taskid) throws DAOException {
        String sb = "select isread from sm_msg_user where sm_msg_user.isdelete = 'N' " +
                "and sm_msg_user.destination = 'inbox'  AND sm_msg_user.pk_message = '" +
                taskid +
                "' and sm_msg_user.pk_user ='" +
                InvocationInfoProxy.getInstance().getUserId() +
                "'";
		String isread = (String) getBaseDAO().executeQuery(sb, new ColumnProcessor());
		if (isread != null && isread.equals("N")) {
			InvocationInfoProxy.getInstance().getUserId();
			getBaseDAO().executeUpdate("UPDATE sm_msg_user" + "   SET isread = 'Y'"
					+ " WHERE sm_msg_user.isdelete = 'N'" + "   AND sm_msg_user.destination = 'inbox'"
					+ "   AND sm_msg_user.pk_message = '" + taskid + "' and sm_msg_user.pk_user ='"+InvocationInfoProxy.getInstance().getUserId()+"'");

		}
	}

}